home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / DataScope 2.0.3 / DataScope2l / TCPSource / userd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  32.8 KB  |  1,545 lines  |  [TEXT/MPS ]

  1. /*
  2. *  USER.C
  3. *  Network library interface routines
  4. *  Generally called by the session layer
  5. *
  6. */
  7. #define MASTERDEF 1
  8. #include <stdio.h>
  9. #include <memory.h>
  10. #include "protocol.h"
  11. #include "data.h"
  12.  
  13. #include <Devices.h>
  14. #include "MacTCPCommonTypes.h"
  15. #include "TCPPB.h"
  16. #include "UDPPB.h"
  17. #include "getmyipaddr.h"
  18.  
  19. #ifdef TRUSTING
  20. #define initMyWorld()    /* noop */
  21. #define myWorld()        /* noop */
  22. #define theirWorld()    /* noop */
  23. #endif  TRUSTING
  24.  
  25. int EtherNet = -99;        /* Signify Drivers */
  26.  
  27. #define LOWWATER 600
  28.  
  29. void initUDPstub(),UDPstub();
  30.  
  31. pascal void TCPNotify();
  32. pascal void UDPNotify();
  33. long openComplete();
  34. long closeComplete();
  35. long sendComplete();
  36.  
  37. /*
  38.  * UDP Stuff
  39.  */
  40.  
  41. #define    UDPBUFSIZ    (1024*8)
  42. #define    getUPB(x,y,z,a)    (UDPiopb *)getPB(x,y,z,a)
  43.  
  44. typedef struct UDPRec {
  45.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  46.     char   *buffer;                    /* Where the immovable UDP buffer is */
  47.     uint    port;                    /* Which UDP port to use */
  48.     } UDPRec, *UDPRPtr;
  49.  
  50. UDPRPtr uport[ NPORTS];                /* our wonderful little thingies. */
  51.  
  52. /*
  53.  * TCP Stuff
  54.  */
  55. #define    noError    0
  56. #define TCPBUFSIZ    (1024*8)
  57. #define    MAX_FDS_ELEMS    32
  58. #define    MAX_SWDS_ELEMS    16
  59. #define MAX_FREE_PB        128
  60. #define MAX_FREE_SWDS    64
  61.  
  62. #define    Qcall    true
  63. #define    noQcall    false
  64.  
  65. typedef    struct freeEntry {
  66.     int inuse;                        /* is this being used? */
  67.     Ptr    ptr;                        /* Pointer to the free entry */
  68.     } freeEntry;
  69.     
  70. typedef struct exfds {
  71.     int    inuse;                        /* Is this being used */
  72.     wdsEntry fds;                    /* The real data */
  73.     } exfds;
  74.     
  75. typedef struct StreamRec {
  76.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  77.     char   *buffer;                    /* Where the immovable TCP buffer is */
  78.     int        push;                    /* TRUE if we should push next data block */
  79.     char   *sbuffer;                /* Where the send buffer is */
  80.     wdsEntry    fds[MAX_FDS_ELEMS];    /* Free Data Structure list */
  81.     exfds    exFDS[MAX_FDS_ELEMS];    /* exFDS entries */
  82.     int        maxFDSused;                /* Max of the FDS's that have been used */
  83.     } StreamRec, *StreamRPtr;
  84.     
  85. short TCPd = 0;                        /* refnum of TCP drivers */
  86.  
  87. StreamRPtr streams[NPORTS];
  88.  
  89. int numPB=0;                        /* Number of PB's ever allocated  (Perf. mon. only ) */
  90. int numSWDS=0;                        /* Number of SWDS's ever alloc'd (PM Only) */
  91.  
  92. freeEntry    freePB[ MAX_FREE_PB];
  93. freeEntry    freeSWDS[ MAX_FREE_SWDS];
  94.  
  95. /**************************************************************************/
  96. wdsEntry *getSWDS()
  97. {
  98.     int n=0;
  99.     
  100.     while (freeSWDS[n].inuse &&  n<MAX_FREE_SWDS) n++;
  101.     if (n >= MAX_FREE_SWDS)
  102.         return(0L);
  103.     
  104.     freeSWDS[n].inuse=1;
  105.     if (freeSWDS[n].ptr==0L) {
  106.         char temp[50];
  107.         freeSWDS[n].ptr = (char *)NewPtr ( sizeof(wdsEntry) *MAX_SWDS_ELEMS);
  108.         numSWDS++;
  109.         sprintf(temp,"New SWDS(%d)",numSWDS);
  110.         putln(temp);
  111.         }
  112.     return( (wdsEntry *) freeSWDS[n].ptr);
  113. }
  114.  
  115. /**************************************************************************/
  116. returnSWDS( wds)
  117. wdsEntry *wds;
  118. {
  119.     int n=0;
  120.     
  121.     while (freeSWDS[n].ptr != wds && n<MAX_FREE_SWDS) n++;
  122.     if (n >= MAX_FREE_SWDS)
  123.         return(-1);
  124.     freeSWDS[n].inuse=0;
  125. }
  126.  
  127. /**************************************************************************/
  128. TCPiopb *getPB( driver, call, stream, usernum)
  129. int driver, call, usernum;
  130. unsigned long stream;
  131. {
  132.     TCPiopb *pbp;
  133.     int n=0;
  134.     
  135.     while (freePB[n].inuse &&  n<MAX_FREE_PB) n++;
  136.     if (n >= MAX_FREE_PB)
  137.         return(0L);
  138.     
  139.     freePB[n].inuse=1;
  140.     if (freePB[n].ptr==0L) {
  141.         char temp[50];
  142.         
  143.         freePB[n].ptr =(char *)NewPtr ( sizeof(TCPiopb)+sizeof(int) );
  144.         numPB++;
  145.         sprintf(temp,"New PB(%d)",numPB);
  146.         putln(temp);
  147.         }
  148.     pbp = (TCPiopb *)freePB[n].ptr;
  149.  
  150.  
  151.     if (!pbp) {
  152.         putln("GETPB failed! panic! ");
  153.         quit();
  154.         }
  155.     
  156.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  157.     
  158.     pbp->ioCRefNum = driver;
  159.     pbp->tcpStream=stream;
  160.     pbp->csCode = call;
  161.     
  162.     return(pbp);
  163. }
  164.  
  165. /**************************************************************************/
  166. clearPB( pbp, driver, call, stream, usernum)
  167. TCPiopb *pbp;
  168. int driver, call, usernum;
  169. unsigned long stream;
  170. {
  171.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  172.     
  173.     pbp->ioCRefNum = driver;
  174.     pbp->tcpStream=stream;
  175.     pbp->csCode = call;
  176.     
  177. }
  178.  
  179. returnPB( pbp)
  180. TCPiopb *pbp;
  181. {
  182.     int n=0;
  183.     
  184.     while (freePB[n].ptr != pbp && n<MAX_FREE_PB) n++;
  185.     if (n >= MAX_FREE_PB)
  186.         return(-1);
  187.     freePB[n].inuse=0;
  188.     
  189. }
  190.  
  191. /***************************************************************************/
  192. /*  netread
  193. *   Read from a connection buffer into a user buffer.  
  194. *   Returns number of bytes read, < 0 on error
  195. * NOTE:
  196. *    current version very inefficient, but hopefully works.
  197. */
  198. netread(pnum,buffer,n)
  199.     int pnum,n;
  200.     char *buffer;
  201.     {
  202.     StreamRPtr p;
  203.     TCPiopb *pbp;
  204.     int inQ, reqdamt;
  205.     
  206.     if (pnum < 0)            /* check validity */
  207.         return(-2);
  208.  
  209.     if (NULL == (p = streams[pnum]))
  210.         return(-2);
  211.     
  212.     
  213.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  214.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  215.         putln("TCPStatus failed(read)"); return(-1);
  216.         }
  217. #ifdef DEBUGHEADERS    
  218.     { char temp[100];
  219.         sprintf(temp, "Stat: %x(%d)->%x(%d) <%d,%d,%d> [%d,%d] {%d,%d}",
  220.             (int)pbp->csParam.status.remoteHost,
  221.             (int)pbp->csParam.status.remotePort,
  222.             (int)pbp->csParam.status.localHost,
  223.             (int)pbp->csParam.status.localPort,
  224.             (int)pbp->csParam.status.tosFlags,
  225.             (int)pbp->csParam.status.precedence,
  226.             (int)pbp->csParam.status.connectionState,
  227.             (int)pbp->csParam.status.sendWindow,
  228.             (int)pbp->csParam.status.rcvWindow,
  229.             (int)pbp->csParam.status.amtUnackedData,
  230.             (int)pbp->csParam.status.amtUnreadData);
  231.         putln(temp);
  232.     }
  233. #endif DEBUGHEADERS
  234.     
  235.     if (pbp->csParam.status.connectionState !=8) {
  236.         char temp[50];
  237.         sprintf(temp,"CState: %d is %d",(int)pnum, (int)pbp->csParam.status.connectionState);
  238.         putln(temp);
  239.         return(-1);                              /* Connection not established */
  240.         }
  241.     
  242.     inQ = pbp->csParam.status.amtUnreadData;
  243.     reqdamt = n >inQ ? inQ : n;
  244.     
  245.     clearPB( pbp, TCPd, TCPRcv, p->stream, pnum);
  246.     pbp->csParam.receive.rcvBuff = buffer;
  247.     pbp->csParam.receive.rcvBuffLen = reqdamt;
  248.     
  249.     if (reqdamt<1) {                                /* Drop out if no data */
  250.         returnPB(pbp);
  251.         return(0);
  252.         }
  253.     
  254.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  255.         putln( "TCPRcv failed ");
  256.         return(-1);
  257.         }
  258.         
  259.     reqdamt = pbp->csParam.receive.rcvBuffLen;
  260.     if (reqdamt<inQ) {
  261.         netputuev( CONCLASS, CONDATA, pnum);            /* more data to get */
  262.         }
  263.         
  264.     returnPB(pbp);                    /* Trash PB */
  265. #ifdef TESTINGPARMS
  266.     {
  267.         char temp[100];
  268.         sprintf(temp, "NETRead: %d from %d", reqdamt, pnum);
  269.         putln(temp);
  270.     }
  271. #endif TESTINGPARMS
  272.     return(reqdamt);
  273. }
  274.  
  275. /************************************************************************/
  276. /* netwrite
  277. *  write something into the output queue, netsleep routine will come
  278. *  around and send the data, etc.
  279. *
  280. */
  281. netwrite(pnum,buffer,nsend)
  282.     int pnum,nsend;
  283.     char *buffer;
  284.     {
  285.     StreamRPtr p;
  286.     wdsEntry *swds;
  287.     int remaining, queued, n,m;
  288.     TCPiopb *pbp;
  289.     
  290.     if (pnum < 0)
  291.         return(-2);
  292.  
  293.     if ( (p = streams[pnum]) == NULL)
  294.         return(-2);
  295.     
  296.     if ( !nsend )
  297.         return(0);
  298.         
  299.     swds = getSWDS();
  300.     
  301.     reclaim( p);
  302.     compressfds( p->fds);
  303.  
  304.     n=0; remaining = nsend;
  305.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  306.         swds[n].ptr = p->fds[n].ptr;
  307.         if ( p->fds[n].length > remaining) {
  308.             swds[n].length = remaining;
  309.             p->fds[n].length -= remaining;
  310.             p->fds[n].ptr += remaining;
  311.             remaining=0;
  312.             }
  313.         else {
  314.             swds[n].length =  p->fds[n].length;
  315.             remaining -= p->fds[n].length;
  316.             p->fds[n].length = 0;
  317.             p->fds[n].ptr = 0;
  318.             }
  319.         n++;
  320.         }
  321.     if (n>p->maxFDSused) p->maxFDSused=n;
  322.     
  323.     compressfds( p->fds);
  324.     queued = nsend-remaining;
  325.     
  326.     for (m=0; m<n; m++) {
  327.         memcpy( swds[m].ptr, buffer, swds[m].length);    /* Put data in WDS */
  328.         buffer +=swds[m].length;
  329.         }
  330.     swds[m].ptr =0L;
  331.     swds[m].length=0;
  332.     
  333.     pbp=getPB( TCPd, TCPSend, p->stream, pnum);            /* Make send call */
  334.     pbp->csParam.send.wdsPtr = (Ptr) swds;
  335.     pbp->csParam.send.pushFlag = p->push;
  336.     
  337.     pbp->ioCompletion = (TCPIOCompletionProc) sendComplete;            /* Completion routine */
  338.  
  339.     p->push=0;
  340.  
  341.     if (PBControl( (ParmBlkPtr) pbp, Qcall) != noError) {
  342.         putln("TCPSend failed to Q"); return(-1);
  343.         }
  344.     
  345. #ifdef TESTINGPARMS
  346.     putln("TCP Sent");
  347.     { char temp[100];
  348.         sprintf(temp, "TCP Sent: %d of %d on %d [%d/%d]", queued, nsend, pnum,n,p->maxFDSused);
  349.         putln(temp);
  350.     }
  351. #endif TESTINGPARMS
  352.     return(queued);
  353. }
  354.  
  355. /**************************************************************************/
  356. /*  netpush
  357. *   attempt to push the rest of the data from the queue
  358. *   and then return whether the queue is empty or not (0 = empty)
  359. *   returns the number of bytes in the queue.
  360. */
  361. netpush(pnum)
  362.     int pnum;
  363.     {
  364.     StreamRPtr p;
  365.     TCPiopb *pbp;
  366.     int inQ;
  367.     
  368.     if (pnum < 0)
  369.         return(-2);
  370.  
  371.     if (NULL == (p = streams[pnum]))
  372.         return(-2);
  373.  
  374.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  375.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  376.         putln("TCPStatus failed(push)"); return(-1);
  377.         }
  378.     inQ = pbp->csParam.status.amtUnackedData;
  379.     returnPB( pbp);
  380.     
  381.     p->push=1;
  382.     
  383.     return(inQ);
  384.  
  385. }    
  386.  
  387. /**************************************************************************/
  388. /*  netqlen
  389. *   return the number of bytes waiting to be read from the incoming queue.
  390. */
  391. netqlen(pnum)
  392.     int pnum;
  393.     {
  394.     StreamRPtr p;
  395.     TCPiopb *pbp;
  396.     int inQ;
  397.     
  398.     if (pnum < 0)
  399.         return(-2);
  400.  
  401.     if (NULL == (p = streams[pnum]))
  402.         return(-2);
  403.  
  404.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  405.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  406.         putln("TCPStatus failed(qlen)"); return(-1);
  407.         }
  408.     inQ = pbp->csParam.status.amtUnreadData;
  409.     returnPB( pbp);
  410.     
  411.     p->push = 1;
  412.     return(inQ);
  413. }
  414.  
  415. /**************************************************************************/
  416. /*  netroom()
  417. *    return how much room is available in output buffer for a connection
  418. */
  419. netroom(pnum)
  420.     int pnum;
  421.     {
  422.     StreamRPtr p;
  423.     int inQ,n;
  424.     
  425.     if (pnum < 0)
  426.         return(-2);
  427.  
  428.     if (NULL == (p = streams[pnum]))
  429.         return(-2);
  430.  
  431.     reclaim( p);
  432.     compressfds( p->fds);
  433.  
  434.     inQ = n = 0;
  435.     while (p->fds[n].ptr) {
  436.     
  437.         inQ += p->fds[n].length;                /* add up free list space */
  438.         n++;
  439.         }
  440.  
  441.     return(inQ);
  442. }
  443.  
  444. /**************************************************************************/
  445. /* netsegsize and neterrchange and netsetip and netgetip
  446. *
  447. *  set operating parameters to change them from the default values used.
  448. */
  449.  
  450. netsegsize(newsize)
  451.     int newsize;
  452.     {
  453.     int i;
  454.  
  455.     i = nnsegsize;
  456.     nnsegsize = newsize;
  457.  
  458.     return(i);
  459. }
  460.  
  461. /**************************************************************************/
  462. netquench(newcredit)
  463.     int newcredit;
  464.     {
  465.     int i;
  466.  
  467.     i = nncredit;
  468.     nncredit = newcredit;
  469.  
  470.     return(i);
  471. }
  472.  
  473. /**************************************************************************/
  474. netarptime(t)                    /* dlayer timeout in secs */
  475.     int t;
  476.     {
  477.     nndto = t;
  478. }
  479.  
  480. /**************************************************************************/
  481. netsetip(st)
  482.     unsigned char *st;
  483.     {
  484. /*
  485. *  this is a no-op with the MacTCP driver
  486. */
  487. }
  488.  
  489. /**************************************************************************/
  490. netgetip(st)
  491. unsigned char *st;
  492. {
  493.     struct IPParamBlock mypb;
  494.  
  495.     putln("Attempting getmyipaddr");
  496.     
  497.     memset( &mypb, '\0', sizeof(struct IPParamBlock));    /* Default to all zeros */
  498.     
  499.     mypb.ioCRefNum = TCPd;            /* TCP driver has to be open by now */
  500.     mypb.csCode = ipctlGetAddr;
  501.  
  502.     if (PBControl( (ParmBlkPtr) &mypb, noQcall) != noError) {
  503.         putln("Getting my address failed"); 
  504.         return(-1);
  505.         }
  506.     
  507.     memcpy(st, &mypb.ourAddress, 4);    /* copy the address */
  508.     
  509.     /* netmask is here if we want it, too */
  510.     
  511.     return(0);
  512.  
  513. }
  514.  
  515.  
  516. /**************************************************************************/
  517. netsetmask(st)
  518. unsigned char *st;
  519. {
  520.     movebytes(nnmask,st,4);
  521. }
  522.  
  523. /**************************************************************************/
  524. netgetmask(st)
  525. unsigned char *st;
  526. {
  527.     movebytes(st,nnmask,4);
  528. }
  529.  
  530. netfromport(port)            /* next "open" will use this port */
  531. int16 port;
  532. {
  533.     nnfromport = port;
  534.  
  535. }
  536.  
  537. /**************************************************************************/
  538. /*  netest?
  539. *  is a particular session established yet?
  540. *  Returns 0 if the connection is in the established state.
  541. */
  542. netest(pnum)
  543. int pnum;
  544. {
  545.     StreamRPtr p;
  546.     TCPiopb *pbp;
  547.     int inQ;
  548.     
  549.     if (pnum < 0)
  550.         return(-2);
  551.  
  552.     if (NULL == (p = streams[pnum]))
  553.         return(-2);
  554.  
  555.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  556.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  557.         putln("TCPStatus failed(est)");
  558.         inQ = -1;
  559.         }
  560.     else 
  561.         inQ = pbp->csParam.status.connectionState !=8;
  562.     returnPB( pbp);
  563.     
  564.     return(inQ);
  565.  
  566. }
  567.  
  568. /**************************************************************************/
  569. /*  netlisten
  570. *   Listen to a TCP port number and make the connection automatically when
  571. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  572. *   with a CONOPEN event.  Save the port number returned to refer to this
  573. *   connection.
  574. *
  575. *   usage:   portnum = netlisten(service);
  576. *            int service;
  577. *
  578. */
  579. netlisten(serv)
  580. uint serv;
  581. {
  582.     int    pnum;
  583.     StreamRPtr p;
  584.     uint16 nn;
  585.     TCPiopb *pbp;
  586.  
  587.     pnum = makestream();
  588.  
  589.     if (pnum < 0)
  590.         return(-2);
  591.  
  592.     if (NULL == (p = streams[pnum]))
  593.         return(-2);
  594.  
  595.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, pnum);            /* Make Listen call */
  596.     
  597.     pbp->csParam.open.localPort = serv;
  598.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;        /* IO Completion for open */
  599.     
  600.     if (PBControl( (ParmBlkPtr) pbp, Qcall) != noError) {
  601.         putln("TCPListen failed"); return(-1);
  602.         }
  603.         
  604.     return(pnum);
  605. }
  606.  
  607. /***********************************************************************/
  608. /*  netgetftp
  609. *  Provides the information that ftp needs to open a stream back to the
  610. *  originator of the command connection.  The other side's IP number
  611. *  and the port numbers to be used to calculate the default data connection
  612. *  number.  Returns values in an integer array for convenient use in 
  613. *  PORT commands.
  614. */
  615. netgetftp(a,pnum)
  616. int a[];
  617. int pnum;
  618. {
  619.     StreamRPtr p;
  620.     TCPiopb *pbp;
  621.     long temp;
  622.     
  623.     if (pnum < 0)
  624.         return(-2);
  625.  
  626.     if (NULL == (p = streams[pnum]))
  627.         return(-2);
  628.  
  629.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  630.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  631.         putln("TCPStatus failed(getftp)"); return(-1);
  632.         }
  633.  
  634.     temp      = pbp->csParam.status.remoteHost;
  635.     a[0]= (temp>>24) & 0xff;
  636.     a[1]= (temp>>16) & 0xff;
  637.     a[2]= (temp>> 8) & 0xff;
  638.     a[3]= (temp    ) & 0xff;
  639.     temp    = pbp->csParam.status.localPort;
  640.     a[4]= (temp>> 8) & 0xff;
  641.     a[5]= (temp    ) & 0xff;
  642.     temp    = pbp->csParam.status.remotePort;
  643.     a[6]= (temp>> 8) & 0xff;
  644.     a[7]= (temp    ) & 0xff;
  645.  
  646.     returnPB( pbp);
  647. }
  648.  
  649. /**************************************************************************/
  650. /*  netopen
  651. *   Netopen is a cheap way to open a connection without looking up any
  652. *   machine information.  Uses suitable default values for everything.
  653. */
  654. netopen(s,tport)
  655. unsigned char *s;
  656. uint tport;
  657. {
  658.  
  659.     return(netxopen(s,tport,MINRTO,TSENDSIZE,DEFSEG,DEFWINDOW));
  660. }
  661.  
  662.  
  663. /**************************************************************************/
  664. /*  netxopen
  665. *   Open a network socket for the user.
  666. *
  667. */
  668. netxopen(machine,service,rto,mtu,mseg,mwin)
  669. uint32 *machine;
  670. uint service,rto,mtu,mseg,mwin;        /* unix service port number */
  671. {
  672.     int    pnum;
  673.     StreamRPtr p;
  674.     TCPiopb *pbp;
  675.     char temp[100];
  676.     
  677.     pnum = makestream();
  678.  
  679.     if (pnum < 0)
  680.         return(-2);
  681.  
  682.     if (NULL == (p = streams[pnum]))
  683.         return(-2);
  684.  
  685.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, pnum);            /* Make Listen call */
  686.     
  687.     pbp->csParam.open.remoteHost = *machine;            /* IP # */
  688.     pbp->csParam.open.remotePort = service;                /* Port */
  689.     pbp->csParam.open.localPort = nnfromport;            /* My Port */
  690.     nnfromport=0;                                            /* Next one is random */
  691.     
  692.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;    /* IO Completion for open */
  693.     
  694.     if (PBControl( (ParmBlkPtr) pbp, Qcall) != noError) {
  695.         putln("TCPOpen failed(Active)"); return(-1);
  696.         }
  697.     sprintf(temp,"TCPOpen on %d",pnum);
  698.     putln(temp);
  699.     return(pnum);
  700. }
  701.  
  702.  
  703. /**************************************************************************/
  704. /* netclose
  705. *  Do appropriate actions to return connection state to SCLOSED which
  706. *  enables the memory for that port to be reused.
  707. *
  708. *    Specifically:
  709. *        o If status is closed, then release the data structures
  710. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  711. *            which should make the session layer call us again
  712. */
  713. netclose(pnum)
  714. int pnum;
  715. {
  716.     StreamRPtr p;
  717.     TCPiopb *pbp;
  718.     int errorCode=0;
  719.     int status;
  720.  
  721.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  722.         return(-1);
  723.  
  724.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  725.         return (1);
  726.  
  727.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  728.     if ((errorCode = PBControl( (ParmBlkPtr) pbp, noQcall)) != noError) {
  729.         if ( errorCode == invalidStreamPtr) {
  730.             putln("TCPStatus failed because of bad stream pointer (close)");
  731.             return(-1);
  732.             }
  733.         else
  734.             status=0;
  735.         }
  736.     else 
  737.         status = pbp->csParam.status.connectionState;            /* The connection Status */
  738.  
  739.     if (status < 18 && status >2 ) {                            /* We aren't closed yet ! */
  740.         char temp[50];
  741.         sprintf(temp, "TCPClose being attempted state ...[%d]",status);    /* Prolly because outstanding close */
  742.         putln(temp);
  743.         clearPB( pbp, TCPd, TCPClose, p->stream, pnum);            /* Make Close call */
  744.         pbp->ioCompletion = (TCPIOCompletionProc) closeComplete;                        /* IO Completion for close */
  745.         if ((errorCode=PBControl( (ParmBlkPtr) pbp, Qcall)) != noError) {
  746.             char temp[50];
  747.             sprintf(temp, "TCPClose failed...[%d]",errorCode);    /* Prolly because outstanding close */
  748.             putln(temp);
  749.             }
  750.         return (0);                                            /* Return with OK */
  751.         }
  752.  
  753.     /* IF we got here, we must be at closed state, so free memory */
  754.  
  755.     putln("TCP Being Released...... ");
  756.     clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Release call */
  757.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  758.         putln("TCPRelease failed"); return(-1);
  759.         }
  760.     
  761.     DisposPtr( (Ptr)  p->buffer);                /* Free Receive Buffer */
  762.     DisposPtr( (Ptr)  p->sbuffer);                /* Free Send Buffer */
  763.     DisposPtr( (Ptr)  p);                        /* Free Stream Structure */
  764.     streams[pnum]=0L;
  765.  
  766.     returnPB(pbp);
  767.     return(0);
  768. }
  769.  
  770. /**************************************************************************/
  771. /* netabort
  772. *    Nuke the connection, NOW!
  773. */
  774. netabort(pnum)
  775. int pnum;
  776. {
  777.     StreamRPtr p;
  778.     TCPiopb *pbp;
  779.     int errorCode=0;
  780.  
  781.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  782.         return(-1);
  783.  
  784.     if ((p = streams[pnum]) != NULL) {            /* something there */
  785.         pbp=getPB( TCPd, TCPAbort, p->stream, pnum);            /* Make Close call */
  786.         if ((errorCode=PBControl( (ParmBlkPtr) pbp, noQcall)) != noError) {
  787.             char temp[50];
  788.             sprintf(temp, "TCPAbort failed...[%d]",errorCode);
  789.             putln(temp);
  790.             }
  791.         clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Close call */
  792.         if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  793.             putln("TCPRelease failed"); return(-1);
  794.             }
  795.         }
  796.     else
  797.         return(1);
  798.     
  799.     DisposPtr( (Ptr)  p->buffer);                /* Free Receive Buffer */
  800.     DisposPtr( (Ptr)  p->sbuffer);                /* Free Send Buffer */
  801.     DisposPtr( (Ptr)  p);                        /* Free Stream Structure */
  802.     streams[pnum]=0L;
  803.  
  804.     returnPB(pbp);
  805.     return(0);
  806. }
  807.  
  808. /**************************************************************************/
  809. /*  netinit
  810. *   Calls all of the various initialization routines that set up queueing
  811. *   variables, static values, reads configuration files, etc.
  812. */
  813.  
  814. netinit()
  815. {
  816.     int i;
  817.     
  818.     for (i=0; i<NPORTS;i++)
  819.         streams[i]= (StreamRPtr) 0;
  820.         
  821.     for (i=0; i<NPORTS;i++)
  822.         uport[i]= (UDPRPtr) 0;
  823.     
  824.     if (opendriver(".IPP",&TCPd) != noError) {
  825.         putln( "Couldn't open IP driver ");
  826.         quit();
  827.         }
  828.         
  829.     initMyWorld();
  830.     initUDPstub( UDPNotify);
  831.     
  832.     return(0);                /* set up empty packets */
  833. }
  834.  
  835. /*************************************************************************/
  836. /*  netshut
  837. *   Close all the connections and turn off the hardware.
  838. */
  839. netshut()
  840.     {
  841.     int i;
  842.  
  843.     for (i=0; i < NPORTS ; i++) 
  844.         if (streams[i] != (StreamRPtr) NULL)
  845.             netabort(i);                        /* Prolly should abort */
  846.     for (i=0; i < NPORTS ; i++) 
  847.         if (uport[i] != (UDPRPtr) NULL)
  848.             netuclose(uport[i]->port);            /* Shut down UDP too... */
  849. #ifdef SAFE
  850.     CloseDriver( TCPd);
  851. #endif SAFE
  852. }
  853.  
  854. /**************************************************************************/
  855. /*
  856.  * Returns an empty stream
  857.  */ 
  858. makestream()
  859. {
  860.     int    pnum;
  861.     StreamRPtr p;
  862.     TCPiopb *pbp;
  863.     int i;
  864.     
  865.     for ( pnum=0; streams[pnum]!= NULL && pnum<NPORTS; pnum++);
  866.     
  867.     if (pnum >= NPORTS)
  868.         return(-2);
  869.  
  870.     p= streams[pnum] = (StreamRPtr) NewPtr(sizeof(StreamRec));
  871.  
  872.     if ((p->buffer = (char *)NewPtr( TCPBUFSIZ)) == (char *)NULL)
  873.         return(-1);
  874.     if ((p->sbuffer = (char *)NewPtr( TCPBUFSIZ)) == (char *)NULL)
  875.         return(-1);
  876.     
  877.     for (i=0; i<MAX_FDS_ELEMS; i++) {
  878.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  879.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  880.         }
  881.     p->fds[0].length = TCPBUFSIZ;
  882.     p->fds[0].ptr = p->sbuffer;
  883.     p->maxFDSused=0;
  884.     
  885.     pbp=getPB( TCPd, TCPCreate, 0, pnum);            /* Make create call */
  886.     pbp->csParam.create.rcvBuff = p->buffer;
  887.     pbp->csParam.create.rcvBuffLen = TCPBUFSIZ;
  888.     pbp->csParam.create.notifyProc = TCPNotify;
  889.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  890.         putln("TCPCreate failed"); return(-1);
  891.         }
  892.     
  893.     p->stream = pbp->tcpStream;
  894.     
  895.     putln("Made a new stream");
  896.     returnPB(pbp);
  897.     return(pnum);
  898. }
  899.  
  900.  
  901. /**************************************************************************/
  902. pascal void TCPNotify( streamPtr, code, uptr, terminReason, icmpMsg)
  903. StreamPtr streamPtr;
  904. unsigned short code;
  905. unsigned short terminReason;
  906. struct ICMPReport *icmpMsg;
  907. Ptr uptr;   /* user data pointer */
  908. {
  909.     StreamRPtr p;
  910.     int pnum;
  911.     
  912.     myWorld();
  913.     pnum= findbystream(streamPtr);
  914.     
  915.     if (pnum<0 || (p=streams[pnum])==0L) {
  916.         theirWorld();
  917.         return;
  918.         }
  919.     
  920.     switch( code) {
  921.         case TCPTerminate:
  922.         case TCPClosing:
  923.             netputevent(CONCLASS, CONCLOSE, pnum);
  924.             break;
  925.         case TCPULPTimeout:
  926.             netputevent(CONCLASS, CONFAIL, pnum);
  927.             break;
  928.         case TCPDataArrival:
  929.         case TCPUrgent:
  930.             netputuev(CONCLASS, CONDATA, pnum);
  931.             break;
  932.         case TCPICMPReceived:
  933.         default:
  934.             break;
  935.         }
  936.     theirWorld();
  937.     return;
  938. }
  939.  
  940. /**************************************************************************/
  941. int findbystream( streamPtr)
  942. StreamPtr streamPtr;
  943. {
  944.     int pnum=0;
  945.     
  946.     while (pnum<NPORTS &&
  947.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  948.         pnum++;
  949.     if (pnum >=NPORTS)
  950.         return(-1);
  951.     else
  952.         return(pnum);
  953. }
  954.  
  955. /*************************************************************************/
  956. /*  netopen2
  957. *   Send out repeat SYN on a connection which is not open yet
  958. *   Checks, and only sends one if needed.
  959. *   Returns 1 if the state is still SYNS and 0 if the connection has proceeded.
  960. *   The timing is all handled at a higher layer.
  961. */
  962. netopen2(pnum)
  963. int pnum;
  964. {
  965.     return( netest(pnum));
  966. }
  967.  
  968. /**************************************************************************/
  969. long openComplete( pbp)
  970. TCPiopb *pbp;
  971. {
  972.     StreamRPtr p;
  973.     int pnum;
  974.     
  975.     myWorld();
  976.     pnum= findbystream(pbp->tcpStream);
  977.     
  978.     if (pnum<0 || (p=streams[pnum])==0L) {
  979.         theirWorld();
  980.         return(-1);
  981.         }
  982.         
  983.     if (pbp->ioResult !=noError) 
  984.         netputevent(CONCLASS, CONFAIL, pnum);            /* Failure ... */
  985.     else 
  986.         netputevent(CONCLASS, CONOPEN, pnum);            /* Success ! */
  987.  
  988.     returnPB( pbp);
  989.  
  990.     theirWorld();
  991.     return(0);
  992.     
  993. }
  994.  
  995. /**************************************************************************/
  996. long sendComplete( pbp)
  997. TCPiopb *pbp;
  998. {
  999.     StreamRPtr p;
  1000.     int pnum;
  1001.     wdsEntry *swds;
  1002.     int i=0,j=0;
  1003.     
  1004.     myWorld();
  1005.     swds = (wdsEntry *) pbp->csParam.send.wdsPtr;
  1006.     
  1007.     pnum= findbystream(pbp->tcpStream);
  1008.     if (pnum<0 || (p=streams[pnum])==0L) {
  1009.         theirWorld();
  1010.         return(-1);
  1011.         }
  1012.  
  1013.     returnSWDS( swds);
  1014.     returnPB( pbp);
  1015.  
  1016.     giveback( p, pbp->csParam.send.wdsPtr);            /* Give this back.... NOW */
  1017.     
  1018.     theirWorld();
  1019.     return(0);
  1020. }
  1021.  
  1022.  
  1023. /**************************************************************************/
  1024. long closeComplete( pbp)
  1025. TCPiopb *pbp;
  1026. {
  1027.     StreamRPtr p;
  1028.     int pnum;
  1029.     
  1030.     myWorld();
  1031.     pnum= findbystream(pbp->tcpStream);
  1032.     
  1033.     if (pnum<0 || (p=streams[pnum])==0L) {
  1034.         theirWorld();
  1035.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1036.         return(-1);
  1037.         }
  1038.         
  1039.     if (pbp->ioResult !=noError) 
  1040.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1041.     else 
  1042.         netputevent(SCLASS, CLOSEDONE, pnum);            /* Success ! */
  1043.  
  1044.     returnPB( pbp);
  1045.  
  1046.     theirWorld();
  1047.     return(0);
  1048.     
  1049. }
  1050.  
  1051.  
  1052. /**************************************************************************/
  1053. /*
  1054.  *     compressfds( fds)
  1055.  *        compress an fds data structure to make everyone happy
  1056.  */
  1057.  
  1058. compressfds( fds)
  1059. wdsEntry *fds;
  1060. {
  1061.     int n,m,compressed;
  1062.     
  1063.     compressed = 0;
  1064.     
  1065.     while ( !compressed) {
  1066.         compressed=1;
  1067.         for (n=0; n< MAX_FDS_ELEMS; n++) {                /* Slow Forwards */
  1068.             if (fds[n].ptr) {                                /* Do if N exists */
  1069.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) {    /* Fast Backwards */
  1070.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  1071.                         fds[n].length+=fds[m].length;
  1072.                         fds[n].ptr = fds[m].ptr;
  1073.                         fds[m].ptr=0L;
  1074.                         fds[m].length=0;
  1075.                         compressed=0;
  1076.                         }
  1077. #ifdef CHECKBOTHWAYZ
  1078.                     else 
  1079.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) {
  1080.                         fds[m].length+=fds[n].length;
  1081.                         fds[n].ptr=0L;
  1082.                         fds[n].length=0;
  1083.                         compressed=0;
  1084.                         }
  1085. #endif CHECKBOTHWAYZ
  1086.                     }
  1087.                 }
  1088.             }
  1089.         }
  1090.     m=0;n=0;
  1091.     
  1092.     /* Close the gaps */
  1093.     
  1094.     while (n+m < MAX_FDS_ELEMS) {
  1095.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS) {
  1096.             m++;            /* increase gap to valid entry */
  1097.             }
  1098.         if (n+m<MAX_FDS_ELEMS)
  1099.             fds[n]=fds[n+m];
  1100.         n++;
  1101.         }
  1102.     
  1103.     /* Get rid of the empty spaces */
  1104.     
  1105.     n--;        /* for the next loop */
  1106.     while (n < MAX_FDS_ELEMS) {
  1107.         fds[n].ptr=0; fds[n++].length=0;
  1108.         }
  1109. }
  1110.  
  1111. /**************************************************************************/
  1112. /* 
  1113.  *    reclaim( p) -
  1114.  *        reclaims buffer space to stream (from pointer p) into the FDS list 
  1115.  */
  1116.  
  1117. reclaim(p)
  1118. StreamRPtr p;
  1119. {
  1120.     int n=0, offset=0;
  1121.     
  1122.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  1123.     
  1124.     if (offset >= MAX_FDS_ELEMS) {
  1125.         putln("Couldn't reclaim because offset was too large ");
  1126.         return(0);
  1127.         }
  1128.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) {
  1129.         if (p->exFDS[ n].inuse) {
  1130.             p->fds[ offset++]=p->exFDS[ n].fds;
  1131.             p->exFDS[ n].inuse = 0;
  1132.             }
  1133.         }
  1134. }
  1135.  
  1136. /**************************************************************************/
  1137. /*
  1138.  *    giveback( p, wds) -
  1139.  *        gives WDS entries back to the stream by putting them in the 
  1140.  *        mutually exclusive buffer.
  1141.  *    p -> stream
  1142.  *    wds -> wds array
  1143.  */
  1144. giveback( p, wds)
  1145. StreamRPtr p;
  1146. wdsEntry *wds;
  1147. {
  1148.     int n=0, m=0;
  1149.     
  1150.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) {
  1151.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  1152.         if (m> MAX_FDS_ELEMS)
  1153.             return(-1);                /* No room in the RECLAIMation center */
  1154.         else {
  1155.             p->exFDS[ m].inuse =1;
  1156.             p->exFDS[ m].fds = wds[n];
  1157.             m++;
  1158.             }
  1159.         n++;
  1160.         }
  1161. }
  1162.  
  1163.  
  1164.  
  1165. /*****************************************************************************
  1166.  *
  1167.  * Here lie the awful UDP routines, I put them here for the drivers from Apple.
  1168.  *
  1169.  */
  1170.  
  1171.  int UDPlisten =0;                /* what port the old routines listen for */
  1172.  
  1173.  
  1174. /****************************************************************************/
  1175. /*                    New UDP routines....                                    */
  1176. /****************************************************************************/
  1177.  
  1178. /**************************************************************************/
  1179. /*
  1180.  * netuopen (port)             - open the udp port "Port"
  1181.  */
  1182.  
  1183. netuopen(port)
  1184. int port;
  1185. {
  1186.  
  1187.     return(makeuport( port));
  1188. }
  1189.  
  1190. /**************************************************************************/
  1191. /*
  1192.  * netuclose( port)             - close the udp port 
  1193.  */
  1194.  
  1195. netuclose( port)
  1196. int port;
  1197. {
  1198.     UDPRPtr p;
  1199.     UDPiopb *pbp;
  1200.     int pnum;
  1201.     
  1202.     pnum= UDPfindport( port);
  1203.     
  1204.     if (pnum<0)
  1205.         return(-1);
  1206.     
  1207.     p=uport[pnum];
  1208.     
  1209.     pbp = getUPB( TCPd, UDPRelease, p->stream, 0);
  1210.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  1211.         putln("UDPClose failed"); return(-1);
  1212.         }
  1213.     DisposPtr( (Ptr)  p->buffer);
  1214.     DisposPtr( (Ptr)  uport[pnum]);
  1215.     uport[pnum]=0;                /* use me again */
  1216.     
  1217.     returnPB( pbp);
  1218. }
  1219.  
  1220. /**************************************************************************/
  1221. /*
  1222.  *    netuget( port, buffer,len, who,where)
  1223.  *                    - read up to len bytes from port port into buffer buffer, noting
  1224.  *                        who it was from and where....
  1225.  */
  1226.  
  1227. netuget( port, buffer, len, who, where)
  1228. int port, len;
  1229. int *who, *where;
  1230. char *buffer;
  1231. {
  1232.     int pnum, length;
  1233.     UDPRPtr p;
  1234.     UDPiopb *pbp;
  1235.     
  1236.     pnum= UDPfindport( port);
  1237.     
  1238.     if (pnum<0)
  1239.         return(-1);
  1240.     
  1241.     p=uport[pnum];
  1242.     
  1243.     pbp= getUPB( TCPd, UDPRead, p->stream, 0);
  1244.     pbp->csParam.receive.timeOut = 1;                            /* time out at one sec. */
  1245.     
  1246.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  1247.         putln("UDPRead failed"); return(-1);
  1248.         }
  1249.     
  1250.     length = pbp->csParam.receive.rcvBuffLen;                /* look how BIG it is */
  1251.     length = length > len ? len:length;
  1252.     
  1253.     memcpy( buffer, pbp->csParam.receive.rcvBuff,length);
  1254.     
  1255.     pbp->csCode = UDPBfrReturn;                                /* Let my buffer go.. */
  1256.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  1257.         putln("UDPReturn failed"); return(-1);
  1258.         }
  1259.         
  1260.     returnPB( pbp);
  1261.     
  1262.     return(length);
  1263. }
  1264.  
  1265. /**************************************************************************/
  1266. netuput( machine, port, myport, buffer, n)
  1267. long *machine;
  1268. char *buffer;
  1269. int port, myport;
  1270. int n;
  1271. {
  1272.     wdsEntry wds[2];
  1273.     UDPRPtr p;
  1274.     UDPiopb *pbp; int pnum;
  1275.     
  1276.     pnum= UDPfindport( myport);
  1277.     
  1278.     if (pnum<0)
  1279.         return(-1);
  1280.     
  1281.     p=uport[pnum];
  1282.     
  1283.     pbp= getUPB( TCPd, UDPWrite, p->stream, 0);
  1284.     pbp->csParam.send.remoteHost = *machine;
  1285.     pbp->csParam.send.remotePort = port;
  1286.     pbp->csParam.send.checkSum   = 1;                    /* Do do that checksum that you do so well */
  1287.     pbp->csParam.send.wdsPtr = (Ptr) wds;
  1288.     pbp->csParam.send.remoteHost = *machine;
  1289.     
  1290.     wds[0].ptr = buffer;
  1291.     wds[0].length=n;
  1292.     wds[1].ptr = (char *) 0L; wds[1].length=0;
  1293.     
  1294.     if (PBControl( (ParmBlkPtr) pbp, noQcall) != noError) {
  1295.         putln("UDPReturn failed"); return(-1);
  1296.         }
  1297.         
  1298.     returnPB( pbp);
  1299.     return(0);
  1300. }
  1301.  
  1302.  
  1303. /****************************************************************************/
  1304. /*  neturead
  1305. *   get the data from the UDP buffer
  1306. *   Returns the number of bytes transferred into your buffer, -1 if none here
  1307. *   This needs work.
  1308. */
  1309. neturead(buffer)
  1310. char *buffer;
  1311. {
  1312.     int who, where;
  1313.     
  1314.     if (!UDPlisten)
  1315.         return(-1);
  1316.         
  1317.     return( netuget( UDPlisten, buffer, 512, &who, &where));
  1318. }
  1319.  
  1320. /***************************************************************************/
  1321. /*  netulisten
  1322. *   Specify which UDP port number to listen to.
  1323. *   Can only listen to one at a time.
  1324. */
  1325. netulisten(port)
  1326. int port;
  1327. {
  1328.     char temp[50];
  1329.     int pnum;
  1330.  
  1331.     
  1332.     sprintf( temp, "UDP listening on ....%d", port);
  1333.     putln(temp);
  1334.     
  1335.     UDPlisten = port;
  1336.     
  1337.     if ( (pnum=UDPfindport( port))<0)
  1338.         pnum= netuopen(port);
  1339.     
  1340.     return (pnum);
  1341. }
  1342.  
  1343. /***************************************************************************/
  1344. /*  netusend
  1345. *   send some data out in a UDP packet
  1346. *   uses the preinitialized data in the port packet ulist.udpout
  1347. *   
  1348. *   returns 0 on okay send, nonzero on error
  1349. */
  1350. netusend(machine,port,retport,buffer,n)
  1351. unsigned char *machine,*buffer;
  1352. unsigned int port,retport;
  1353. int n;
  1354. {
  1355.     /* find if port is open */
  1356.     if ( UDPfindport( retport)<0)
  1357.         netuopen(retport);
  1358.     
  1359.     /* Send data */
  1360.     netuput( machine, port, retport, buffer,n);
  1361. }
  1362.  
  1363. /**************************************************************************/
  1364. makeuport( port)
  1365. int port;
  1366. {
  1367.     int    pnum;
  1368.     UDPRPtr p;
  1369.     UDPiopb *pbp;
  1370.     int i;
  1371.     
  1372.     for ( pnum=0; uport[pnum]!= NULL && pnum<NPORTS; pnum++);
  1373.     
  1374.     if (pnum >= NPORTS)
  1375.         return(-2);
  1376.  
  1377.     p= uport[pnum] = (UDPRPtr)NewPtr(sizeof(UDPRec));
  1378.  
  1379.     if ((p->buffer = (char *)NewPtr( UDPBUFSIZ)) == (char *)NULL)
  1380.         return(-1);
  1381.     
  1382.     
  1383.     pbp=getUPB( TCPd, UDPCreate, 0, pnum);            /* Make create call */
  1384.     
  1385.     pbp->csParam.create.rcvBuff  = p->buffer;
  1386.     pbp->csParam.create.rcvBuffLen= UDPBUFSIZ;
  1387.     pbp->csParam.create.notifyProc     = UDPNotify;
  1388.     pbp->csParam.create.localPort = port;
  1389.     
  1390.     if ((i=PBControl( (ParmBlkPtr) pbp, noQcall)) != noError) {
  1391.         char temp[50];
  1392.         sprintf(temp, "UDPCreate failed (%d)",i);
  1393.         putln(temp);
  1394.         return(-1);
  1395.         }
  1396.     else {
  1397.         char temp[50];
  1398.         sprintf(temp, "UDPCreate successfull on %d(%d) [%x]",port,pnum,pbp->udpStream);
  1399.         putln(temp);
  1400.         }
  1401.     
  1402.     p->stream = pbp->udpStream;
  1403.     p->port = port;
  1404.     
  1405.     putln("Made a new UPORT");
  1406.     returnPB(pbp);
  1407.     return(pnum);
  1408. }
  1409.  
  1410. /**************************************************************************/
  1411. int ufindbystream( streamPtr)
  1412. StreamPtr streamPtr;
  1413. {
  1414.     int pnum=0;
  1415.     
  1416.     while (pnum<NPORTS &&
  1417.             ( uport[pnum] ==(UDPRPtr)0L || streamPtr !=uport[pnum]->stream))
  1418.         pnum++;
  1419.     if (pnum >=NPORTS)
  1420.         return(-1);
  1421.     else
  1422.         return(pnum);
  1423. }
  1424.  
  1425. /**************************************************************************/
  1426. int UDPfindport( port)
  1427. int port;
  1428. {
  1429.     int pnum=0;
  1430.     
  1431.     while (pnum<NPORTS &&
  1432.             ( uport[pnum] ==(UDPRPtr)0L || port !=uport[pnum]->port))
  1433.         pnum++;
  1434.     if (pnum >=NPORTS)
  1435.         return(-1);
  1436.     else
  1437.         return(pnum);
  1438. }
  1439.  
  1440. /**************************************************************************/
  1441. pascal void UDPNotify( streamPtr, code, uptr, icmpMsg)
  1442. StreamPtr streamPtr;
  1443. unsigned short code;
  1444. struct ICMPReport *icmpMsg;
  1445. Ptr uptr;   /* user data */
  1446. {
  1447.     UDPRPtr p;
  1448.     int pnum;
  1449.     
  1450.     myWorld();
  1451.     pnum= ufindbystream(streamPtr);
  1452.     
  1453.     if (pnum<0 || (p=uport[pnum])==0L) {
  1454.         theirWorld();
  1455.         return;
  1456.         }
  1457.     
  1458.     switch( code) {
  1459.         case UDPDataArrival:
  1460.             netputuev(USERCLASS,UDPDATA,p->port);        /* post that it is here */
  1461.         default:
  1462.             break;
  1463.         }
  1464.     theirWorld();
  1465.     return;
  1466. }
  1467.  
  1468. netconfig( hardware)
  1469. char *hardware;
  1470. {
  1471.     putln("I'm a driver TCP, I don't need hardware.....");
  1472.     initipnum(0);
  1473. }
  1474.  
  1475. netarpme(s)
  1476. char *s;
  1477. {
  1478.     putln("Drivers don't need arps, either.");
  1479. }
  1480.  
  1481. netsetgate(s)
  1482. char *s;
  1483. {
  1484.     putln("Yeah, right....");
  1485. }
  1486.  
  1487. netgetrarp()
  1488. {
  1489.     putln("RARP handled above me....");
  1490. }
  1491.  
  1492. uint8 *getdlayer()
  1493. {
  1494.     putln("This shouldn't be called...");
  1495.     return(0L);
  1496. }
  1497.  
  1498. tcpsend()
  1499. {
  1500. }
  1501.  
  1502. demux()
  1503. {
  1504.     return(0);
  1505. }
  1506.  
  1507. /*************************************************************************/
  1508. /* neteventinit
  1509. *  load up the pointers for the event queue
  1510. *  makes a circular list to follow, required for error messages
  1511. */
  1512. neteventinit()
  1513.     {
  1514.     int i;
  1515.  
  1516.     for (i=0; i < NEVENTS; i++)
  1517.         nnq[i].next = i+1;
  1518.  
  1519.     nnq[NEVENTS-1].next = -1;
  1520.  
  1521.     nnefirst = 0;
  1522.     nnelast = 0;
  1523.     nnefree = 1;
  1524. }
  1525.  
  1526. getATaddress()
  1527. {
  1528. }
  1529.  
  1530. KIPfindgate()
  1531. {
  1532. }
  1533.  
  1534. KIPgetns()
  1535. {
  1536. }
  1537.  
  1538. KIPgetdynam()
  1539. {
  1540. }
  1541.  
  1542. KIPregister()
  1543. {
  1544. }
  1545.